package com.cybertron.ironhide.manage.common.auth.admin;

import java.util.ArrayList;
import java.util.List;

import javax.annotation.Resource;

import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.DisabledAccountException;
import org.apache.shiro.authc.LockedAccountException;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.credential.CredentialsMatcher;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.web.subject.WebSubject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import com.cybertron.ironhide.manage.common.exception.IncorrectCaptchaException;
import com.cybertron.ironhide.manage.domain.User;
import com.cybertron.ironhide.manage.service.UserService;
import com.octo.captcha.service.CaptchaService;

@Component
public class AdminRealm extends AuthorizingRealm {

	private static final Logger log = LoggerFactory
			.getLogger(AuthorizingRealm.class);

	@Resource
	private CaptchaService captchaService;

	@Resource
	private UserService userService;

	public static final String ROLES_SEPARATOR = ",";

	public AdminRealm() {
		super();
		CredentialsMatcher matcher = new HashedCredentialsMatcher("MD5");
		setCredentialsMatcher(matcher);
		setCachingEnabled(true);
	}

	@Override
	public boolean supports(AuthenticationToken token) {
		return token != null
				&& AdminUsernamePasswordToken.class.isAssignableFrom(token
						.getClass());
	}

	@Override
	protected AuthorizationInfo doGetAuthorizationInfo(
			PrincipalCollection principals) {
		User user = (User) principals.fromRealm(getName()).iterator().next();
		SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
		List<String> roles = new ArrayList<String>();
		String[] roleArr = StringUtils.split(user.getRole(), ROLES_SEPARATOR);
		for (String role : roleArr) {
			roles.add(role);
		}
		info.addRoles(roles);
		return info;

	}

	@Override
	protected AuthenticationInfo doGetAuthenticationInfo(
			AuthenticationToken authcToken) throws AuthenticationException {
		AdminUsernamePasswordToken token = (AdminUsernamePasswordToken) authcToken;
		String username = token.getUsername();
		String captcha = token.getCaptcha();
		boolean isCaptcha = validateCaptcha(captcha);
		if (isCaptcha == false) {
			throw new IncorrectCaptchaException("Valid Captch Error");
		}
		User user = userService.selectByUserName(username);
		if (user != null) {
			if (user.isAccountEnable() == false) {
				throw new DisabledAccountException("member [" + username
						+ "] is disabled");
			}
			if (user.isAccountLocked()) {
				throw new LockedAccountException("member [" + username
						+ "] is locked");
			}
			return new SimpleAuthenticationInfo(user, user.getPassword(),
					getName());
		}
		return null;
	}

	/**
	 * 校验验证码.
	 * 
	 * @param request
	 *            HttpServletRequest对象
	 * 
	 */
	protected boolean validateCaptcha(String captcha) {
		WebSubject webSubject = (WebSubject) SecurityUtils.getSubject();
		String captchaID = (String) webSubject.getSession().getId();
		String challengeResponse = StringUtils.upperCase(captcha);
		try {
			return captchaService.validateResponseForID(captchaID,
					challengeResponse);
		} catch (Exception e) {
			if (log.isDebugEnabled()) {
				log.debug(e.getMessage());
			}
		}
		return false;
	}

}
